<?php

namespace App\Repository\Repositories;
use App\Helpers\Image;
use App\Http\Controllers\Controller;
use App\Http\Serve\Es;
use App\Http\Service\Redisd;
use App\Models\StoreProduct;
use App\Models\StoreProductReply;
use App\Models\StoreVisit;
use App\Models\User;
use App\Repository\RepositoryInterface\ShopInterface;
use Dotenv\Exception\ValidationException;
use Illuminate\Support\Facades\Request;

class ShopRepositories extends Controller implements ShopInterface
{
    protected $shop;
    protected $product;
    protected $use;
    protected $visit;
    public function __construct(StoreProductReply $productReply,StoreProduct $storeProduct,User $user,StoreVisit $storeVisit)
    {
        $this->shop = $productReply;
        $this->product = $storeProduct;
        $this->use = $user;
        $this->visit = $storeVisit;
    }

    //*** why
    /**
     * @return \Illuminate\Http\JsonResponse
     * 查询评论
     */
    public function shopRemarkAll()
    {
        try {
            $data = $this->shop->with(['goods','user'])->paginate(5);
            if (!$data){
                return parent::error('查找失败');
            }
            return parent::success('查找成功',$data);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }

    /**
     * @param $data
     * @return \Illuminate\Http\JsonResponse
     * 添加评论
     */
    public function shopRemarkAdd($data)
    {
        try {
            $result = $this->shop::create($data);
            if (!$result){
                return parent::error('添加失败');
            }
            return parent::success('添加成功');
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }

    /**
     * @param $id
     * @return \Illuminate\Http\JsonResponse
     * 删除评论
     */
    public function shopRemarkDel($id)
    {
        try {
            $result = $this->shop::where('id',$id)->delete();

            if (!$result){
                return parent::error('删除失败');
            }
            return parent::success('删除成功');
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }

    /**
     * @param $data
     * @return \Illuminate\Http\JsonResponse
     * 编辑评论
     */
    public function shopRemarkEdit($data)
    {
        try {
            $result = $this->shop::update($data);
            if (!$result){
                return parent::error('修改失败');
            }
            return parent::success('修改成功');
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }
    /**
     * @param $data
     * @return \Illuminate\Http\JsonResponse
     * 搜索评论
     */
    public function shopRemarkSearch($data)
    {
        try {
            $searchData = $this->shop->with(['goods','user'])->when($data,function ($query,$data){
                if($data['is_reply'] != ""){
                    $query->where("is_reply",$data['is_reply']);
                }
            })->when($data,function ($query,$data){
                if($data['store_name'] != ""){
                    $id = $this->product::where('store_name','like',$data['store_name']."%")->get('id')->toArray();
                    foreach ($id as $k=>$v){
                        $query->where("product_id",$v);
                    }
                }
            })->when($data,function ($query,$data){
                if($data['real_name'] != ""){
                    $uid = $this->use::where('real_name','like',$data['real_name']."%")->get('uid')->toArray();
                    foreach ($uid as $k=>$v){
                        $query->where("uid",$v['uid']);
                    }
                }
            })->paginate(5)->toArray();
            if (!$searchData){
                return parent::error('搜索失败');
            }
            return parent::success('搜索数据',$searchData);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }

    /**
     * @param $file
     * @return false|\Illuminate\Http\JsonResponse|string
     * 上传评论图片
     */
    public function remarkImageUpload($file)
    {
        try {
            $ak = 'gYTXWzI0T90vqwS0tZWe5OXZuP8eMhlXYx7cqkDg';
            $sk = 'sa9WOQFYdnP1NjFRpHYnVVCrTydJnY-jBjW-J_MX';
            $bucket = 'whytest1';
            $url = 'http://why.wyt.plus/';
            //七牛云上传
            $imageUrl = (new Image())->uploadFile($file,$ak,$sk,$bucket,$url);
            return parent::success('上图片',$imageUrl);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     * 热卖商品推荐
     */
    public function recommendShop(){
        try {
            $data = $this->product::where('is_hot','=',1)->get();
            if (!$data){
                return parent::error('热点数据查询失败');
            }
            return parent::success('推荐商品',$data);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }
    /**
     * 评论回复
     */
    public function reply($id,$mark)
    {
        try {
            //商品回复
            $replyResult = StoreProductReply::where('id',$id)->update(['merchant_reply_content'=>$mark]);
            //判断
            if (!$replyResult){
                return parent::error('回复失败');
            }
            return parent::success('回复成功');
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * 曼哈顿算法
     */
    public function manhattans($uid)
    {
        if (count($this->visit::where('uid',$uid)->get()) == 0){//判断该用户有没有浏览记录
            return parent::error('该用户没有浏览记录');
        }
        $users = [];
        $last = [];
        $users_data = $this->visit::get()->groupBy('uid');//根据用户分组
        foreach ($users_data as $k=>$v){//循环处理数组
            foreach ($v as $v_v){
                $last[$v_v['product_id']] = $v_v['count'];
            }
            $users[$k] = $last;
            unset($last);
        }
        $usersArray = json_decode(json_encode($users), true);//转换格式
//        return $usersArray;
        $recommend = $this->recommend($uid, $usersArray);
        if (empty($recommend)){
            return parent::error('无法根据用户习惯推荐商品');
        }
        return parent::success('推荐商品',$recommend);
    }
    /**
     * @param $username
     * 用户id
     * @param $users
     * 用户浏览记录
     * @return array
     * 实现推荐
     */
    public function recommend($username, $users)
    {
        //获得最近用户的name
        $nearest = $this->computeNearestNeighbor($username, $users);
        $nearest = $nearest['0']['user'];
        $recommendations = array();
        //得到最近用户的推荐列表
        $neighborRatings = $users[$nearest];
//        return $neighborRatings;
        if ($this->checkArray($neighborRatings)) {
            $usernameAction = $users[$username];
            foreach ($neighborRatings as $name => $code) {
                //读取自己没有的
                if (!isset($usernameAction[$name])) {
                    $recommendations[] = ['goods' => $name, 'count' => $code];
                }
            }
        }
        $this->sortArrByField($recommendations, 'count', true);
        return $recommendations;
    }

    /**
     * @param $first
     * 第一个坐标点
     * @param $last
     * 第二个坐标点
     * @return float|int
     * 计算曼哈顿距离
     */
    private function manhattan($first, $last)
    {
        $distance = 0;//曼哈顿值
        if ($this->checkArray($first)) {//判断是否为数组
            foreach ($first as $name => $valuefirst) {
                if (isset($last[$name])) {
                    $valuelast = $last[$name];
                    $distance += abs($valuefirst - $valuelast);//两点的坐标值相减取绝对值后相加
                }
            }
        } else {
            $distance = -1;
        }
        return $distance;
    }

    /**
     * @param $username
     * 用户id
     * @param $users
     * 用户浏览数据
     * @return array
     * 返回最近距离用户
     */
    private function computeNearestNeighbor($username, $users)
    {
        $distances = [];
        if ($this->checkArray($users)) {//检查是否为数组
            foreach ($users as $key => $user) {
                if ($key == $username) {
                    continue;
                }
                $distance = $this->manhattan($user, $users[$username]);
                $data = array(
                    'user' => $key,
                    'distance' => $distance,
                );
                $distances[] = $data;
            }
        }
        $this->sortArrByField($distances, 'distance', false);
        return $distances;
    }

    /**
     * @param $array
     * @return bool
     * 检查数组有效性
     */
    private function checkArray($array)
    {
        if (is_array($array) && count($array) > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param $array
     * @param $field
     * @param bool $desc
     * 根据数组的某个值将用户“亲密度”进行排序
     */
    private function sortArrByField(&$array, $field, $desc = false)
    {

        $fieldArr = [];
        foreach ($array as $k => $v) {
            $fieldArr[$k] = $v[$field];
        }
        $sort = $desc == false ? SORT_ASC : SORT_DESC;
        array_multisort($fieldArr, $sort, $array);
    }
    /**
     * zyy
     * @return \Illuminate\Http\JsonResponse
     * 商品查询
     */
    public function shopSendAll(){
        try {
            $shopData = $this->product->where("is_hot","1")->orderBy("sales","desc")->paginate(5)->toArray();

            return parent::success("查询成功",$shopData);
        }catch (\Exception$exception){
            return parent::error($exception->getMessage());
        }
    }
    /**
     * 获取全部商品信息
     */
    public function getShopsAll()
    {
        // TODO: Implement getShopsAll() method.
        try {
            $shopsInfo = $this->product::get();
            return parent::success('商品信息',$shopsInfo);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }
    /**
     * 商品详情
     */
    public function getShopsDetail($id)
    {
        // TODO: Implement getShopsAll() method.
        try {
            $detailInfo = $this->product::where('id',$id)->get();
            return parent::success('商品信息',$detailInfo);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }
    /**
     * 商品评论列表
     */
    public function getShopsRemarks($product_id)
    {
        try {
            //查询结果
            $remarksInfo = $this->shop::with(['goods','user'])->where('product_id',$product_id)->get()->toArray();
            foreach ($remarksInfo as $k=>&$v){
                $v['add_time'] = date('Y-m-d',$v['add_time']);
            }
            return parent::success('评论列表',$remarksInfo);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }
    /**
     * 热数据排行榜
     */
    public function list()
    {
        try {
            //查询全部数据
            $allData = $this->product::where('is_hot',1)->get()->toArray();
            //存入redis
            foreach ($allData as $k=>$v){
                Redisd::getInstance()->zIncrBy('hot',$v['browse'],$v['id']);
            }
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }
    /**
     * 轮播图表
     */
    public function circleImage()
    {
        try {
            //储存数组
            $id = [];
            //取出热点数据
            $data = Redisd::getInstance()->zRevRange('hot',0,3);
            //处理商品数组
            foreach ($data as $k=>$v){
                $id[] = $v;
            }
            $circleImage = $this->product::whereIn('id',$id)->get();
            //处理商品图片
            $image = [];
            foreach ($circleImage as $k=>$v){
                $image[$k]['img'] = $v['image'];
            }
            //返回前端
            return parent::success('轮播图',$image);
        }catch (\Exception $e){
            return parent::error($e->getMessage());
        }
    }

    /**
     * @param $search
     * @return \Illuminate\Http\JsonResponse
     * 首页搜索
     */
    public function homeSearch($search)
    {
        // TODO: Implement homesearch() method.
        if (empty($search['store_name']))
        {
            return parent::error('搜索失败');
        }
        //es搜索
        if (!(new Es())->exists_index('product')){
            return parent::error('索引不存在');
        }
        $data = (new Es())->search_docs('product','product_one',$search);
        return parent::success('搜索结果',$data);
    }

}
